package alex.rsx.reader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Vector;

import alex.rsx.activity.r.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Region;
import android.graphics.Typeface;
import android.graphics.Paint.FontMetrics;
import android.graphics.drawable.GradientDrawable;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Scroller;

import com.alex.books.BookPageFactory;

public class PageWidget extends View {

	private static final String TAG = "PageWidget";
	
	/**
	 * Flip way 翻页方式
	 */
	public static final int FW_DRAG_RL = 0x01;
	public static final int FW_DRAG_UD = 0x02;
	public static final int FW_SLIDE_RL = 0x03;
	public static final int FW_SLIDE_UD = 0x04;
	public static final int FW_SIMULAT = 0x05;

	private static int FLIP_WAY;

	private int mCornerX = 0; // 拖拽点对应的O页脚
	private int mCornerY = 0;
	private Path mPath0;
	private Path mPath1;
	Bitmap mCurPageBitmap = null; // 当前页
	Bitmap mNextPageBitmap = null;

	int mWidth, mHeight;
	PointF mTouch = new PointF(); // 拖拽点
	PointF mBezierStart1 = new PointF(); // 贝塞尔曲线起始点
	PointF mBezierControl1 = new PointF(); // 贝塞尔曲线控制点
	PointF mBeziervertex1 = new PointF(); // 贝塞尔曲线顶点
	PointF mBezierEnd1 = new PointF(); // 贝塞尔曲线结束点

	PointF mBezierStart2 = new PointF(); // 另一条贝塞尔曲线
	PointF mBezierControl2 = new PointF();
	PointF mBeziervertex2 = new PointF();
	PointF mBezierEnd2 = new PointF();

	float mMiddleX;
	float mMiddleY;
	float mDegrees;
	float mTouchToCornerDis;
	ColorMatrixColorFilter mColorMatrixFilter;
	Matrix mMatrix;
	float[] mMatrixArray = { 0, 0, 0, 0, 0, 0, 0, 0, 1.0f };

	boolean mIsRTandLB; // 是否属于右上左下
	float mMaxLength = (float) Math.hypot(mWidth, mHeight);
	int[] mBackShadowColors;
	int[] mBackShadowColors0;
	int[] mFrontShadowColors;
	GradientDrawable mBackShadowDrawableLR;
	GradientDrawable mBackShadowDrawableRL;
	GradientDrawable mFolderShadowDrawableLR;
	GradientDrawable mFolderShadowDrawableRL;
	GradientDrawable mBackShadowDrawableRL0;
	GradientDrawable mBackShadowDrawableRL1;
	GradientDrawable mFrontShadowDrawableHBT;
	GradientDrawable mFrontShadowDrawableHTB;
	GradientDrawable mFrontShadowDrawableVLR;
	GradientDrawable mFrontShadowDrawableVRL;

	Paint mPaint;
	Scroller mScroller;
	Canvas mCurPageCanvas, mNextPageCanvas;
	Bitmap readbg ;
	Context mContext;
	int fontColor;
	private float minSS;
	public PageWidget(Context context) {
		super(context);
		mContext= context;
		// TODO Auto-generated constructor stub
		check();
	}
	
	private void check(){
		Class<?> c = null;
        try {
			c = Class.forName("android.view.View");
			Method m = c.getMethod("setLayerType",int.class,Paint.class);
			if(m != null){
				m.invoke(this, 1,null);
			}
		} catch (ClassNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SecurityException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		} catch (NoSuchMethodException e3) {
			// TODO Auto-generated catch block
			e3.printStackTrace();
		} catch (IllegalArgumentException e4) {
			// TODO Auto-generated catch block
			e4.printStackTrace();
		} catch (IllegalAccessException e4) {
			// TODO Auto-generated catch block
			e4.printStackTrace();
		} catch (InvocationTargetException e5) {
			// TODO Auto-generated catch block
			e5.printStackTrace();
		}
	}
	
	public void setFlipWay(int flipWay){
		mTouch.x = 0;
		mTouch.y = 0;
		FLIP_WAY = flipWay;
		switch (FLIP_WAY) {
		case FW_DRAG_RL:
		case FW_DRAG_UD:
			setOnTouchListener(fw_drag_listener);
			break;
		case FW_SLIDE_RL:
		case FW_SLIDE_UD:
			setOnTouchListener(fw_slide_listener);
			break;
		case FW_SIMULAT:
			mCornerX = 0;
			mCornerY = 0;
			setOnTouchListener(fw_simulat_listener);
			break;
		default:
			break;
		}
	}
	
	private OnTouchListener fw_drag_listener = new OnTouchListener() {
		
		@Override
		public boolean onTouch(View v, MotionEvent e) {
			// TODO Auto-generated method stub

			boolean ret = false;
			if (e.getAction() == MotionEvent.ACTION_DOWN 
					&& (mWidth/4) < e.getX()
					&& e.getX() < (mWidth*3/4)
					&& (mHeight/3) < e.getY()
					&& e.getY() < (mHeight*2/3)) {
				mOnClickListener.onCmdHandle(OnCmdListener.CMD_0);
			} else {
				if (e.getAction() == MotionEvent.ACTION_DOWN) {
					calcCornerXY(e.getX(), e.getY());
					if(BookPageFactory.getInstance().isFirstPage()
					|| BookPageFactory.getInstance().isLastPage()){
					} else{
						abortAnimation();
					}
					
					if (DragToRight()) {
						onDraw0(mNextPageCanvas);
						if (BookPageFactory.getInstance().isFirstPage())
							return false;
						BookPageFactory.getInstance().previousPage();
						onDraw0(mCurPageCanvas);
					} else {
						onDraw0(mCurPageCanvas);
						if (BookPageFactory.getInstance().isLastPage()){
							mOnClickListener.onCmdHandle(OnCmdListener.CMD_1);
							return false;
						}
						BookPageFactory.getInstance().nextPage();
						onDraw0(mNextPageCanvas);
					}
				}
				ret = doTouchEvent(e);
			}
			return ret;
		}
	};
	
	private OnTouchListener fw_slide_listener = new OnTouchListener() {
		
		@Override
		public boolean onTouch(View v, MotionEvent e) {
			// TODO Auto-generated method stub

			boolean ret = false;
			if (e.getAction() == MotionEvent.ACTION_DOWN 
					&& (mWidth/4) < e.getX()
					&& e.getX() < (mWidth*3/4)
					&& (mHeight/3) < e.getY()
					&& e.getY() < (mHeight*2/3)) {
				mOnClickListener.onCmdHandle(OnCmdListener.CMD_0);
			} else {
				if (e.getAction() == MotionEvent.ACTION_DOWN) {
					calcCornerXY(e.getX(), e.getY());
					if(BookPageFactory.getInstance().isFirstPage()
					|| BookPageFactory.getInstance().isLastPage()){
					} else{
						abortAnimation();
					}
					
					if (DragToRight()) {
						onDraw0(mNextPageCanvas);
						if (BookPageFactory.getInstance().isFirstPage())
							return false;
						BookPageFactory.getInstance().previousPage();
						onDraw0(mCurPageCanvas);
					} else {
						onDraw0(mCurPageCanvas);
						if (BookPageFactory.getInstance().isLastPage()){
							mOnClickListener.onCmdHandle(OnCmdListener.CMD_1);
							return false;
						}
						BookPageFactory.getInstance().nextPage();
						onDraw0(mNextPageCanvas);
					}
				}
				ret = doTouchEvent(e);
			}
			return ret;
		}
	};
	
	private OnTouchListener fw_simulat_listener = new OnTouchListener() {
		
		@Override
		public boolean onTouch(View v, MotionEvent e) {
			// TODO Auto-generated method stub

			boolean ret = false;
			if (e.getAction() == MotionEvent.ACTION_DOWN 
					&& (mWidth/4) < e.getX()
					&& e.getX() < (mWidth*3/4)
					&& (mHeight/3) < e.getY()
					&& e.getY() < (mHeight*2/3)) {
				mOnClickListener.onCmdHandle(OnCmdListener.CMD_0);
			} else {
				if (e.getAction() == MotionEvent.ACTION_DOWN) {
					calcCornerXY(e.getX(), e.getY());
					if(BookPageFactory.getInstance().isFirstPage()
					|| BookPageFactory.getInstance().isLastPage()){
					} else{
						abortAnimation();
					}
					onDraw0(mCurPageCanvas);
					if (DragToRight()) {
						
						if (BookPageFactory.getInstance().isFirstPage())
							return false;
						BookPageFactory.getInstance().previousPage();
						onDraw0(mNextPageCanvas);
						
					} else {
						if (BookPageFactory.getInstance().isLastPage()){
							mOnClickListener.onCmdHandle(OnCmdListener.CMD_1);
							return false;
						}
						BookPageFactory.getInstance().nextPage();
						onDraw0(mNextPageCanvas);
					}
				}
				ret = doTouchEvent(e);
			}
			return ret;
		}
	};
	
	private float mDensity;
	public void init(final int screenW, final int screenH, float density){
		mWidth = screenW;
		mHeight = screenH;
		mDensity = density;
		mMaxLength = (float) Math.hypot(mWidth, mHeight);
		mCurPageBitmap = Bitmap.createBitmap(screenW, screenH, Bitmap.Config.ARGB_8888);
		mNextPageBitmap = Bitmap
				.createBitmap(screenW, screenH, Bitmap.Config.ARGB_8888);
		mCurPageCanvas = new Canvas(mCurPageBitmap);
		mNextPageCanvas = new Canvas(mNextPageBitmap);
		mPath0 = new Path();
		mPath1 = new Path();
		createDrawable();

		mPaint = new Paint();
		mPaint.setStyle(Paint.Style.FILL);
		mPaint.setAntiAlias(true);
		ColorMatrix cm = new ColorMatrix();
		float array[] = { 0.55f, 0, 0, 0, 80.0f, 0, 0.55f, 0, 0, 80.0f, 0, 0,
				0.55f, 0, 80.0f, 0, 0, 0, 0.2f, 0 };
		cm.set(array);
		mColorMatrixFilter = new ColorMatrixColorFilter(cm);
		mMatrix = new Matrix();
		mScroller = new Scroller(getContext());

		mTouch.x = 0.01f; // 不让x,y为0,否则在点计算时会有问题
		mTouch.y = 0.01f;

	}

	/**
	 * Author : hmg25 Version: 1.0 Description : 计算拖拽点对应的拖拽脚
	 */
	public void calcCornerXY(float x, float y) {
		if (x <= mWidth / 2)
			mCornerX = 0;
		else
			mCornerX = mWidth;
		if (y <= mHeight / 2)
			mCornerY = 0;
		else
			mCornerY = mHeight;
		if ((mCornerX == 0 && mCornerY == mHeight)
				|| (mCornerX == mWidth && mCornerY == 0))
			mIsRTandLB = true;
		else
			mIsRTandLB = false;
	}

	public boolean doTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		
			if (event.getAction() == MotionEvent.ACTION_MOVE) {
				mTouch.x = event.getX();
				mTouch.y = event.getY();
				this.postInvalidate();
			}
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				mTouch.x = event.getX();
				mTouch.y = event.getY();
				// calcCornerXY(mTouch.x, mTouch.y);
				// this.postInvalidate();
			}
			if (event.getAction() == MotionEvent.ACTION_UP) {
				if(FLIP_WAY == FW_SIMULAT){
					if (canDragOver()) {
						startAnimation(1200);
					} else {
						mTouch.x = mCornerX - 0.09f;
						mTouch.y = mCornerY - 0.09f;
					}
				}else{
					startAnimation(500);
				}
				this.postInvalidate();
			}
		
		// return super.onTouchEvent(event);
		return true;
	}
	
	/**
	 * Author : hmg25 Version: 1.0 Description : 求解直线P1P2和直线P3P4的交点坐标
	 */
	public PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {
		PointF CrossP = new PointF();
		// 二元函数通式： y=ax+b
		float a1 = (P2.y - P1.y) / (P2.x - P1.x);
		float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x);

		float a2 = (P4.y - P3.y) / (P4.x - P3.x);
		float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x);
		CrossP.x = (b2 - b1) / (a1 - a2);
		CrossP.y = a1 * CrossP.x + b1;
		return CrossP;
	}

	private void calcPoints() {
		mMiddleX = (mTouch.x + mCornerX) / 2;
		mMiddleY = (mTouch.y + mCornerY) / 2;
		mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
				* (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
		mBezierControl1.y = mCornerY;
		
		mBezierControl2.x = mCornerX;
		mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
				* (mCornerX - mMiddleX) / (mCornerY - mMiddleY);

		/* Log.i("hmg", "mTouchX  " + mTouch.x + "  mTouchY  " + mTouch.y);
		 Log.i("hmg", "mMiddleX  " + mMiddleX + "  mMiddleY  " + mMiddleY);
		 Log.i("hmg", "mCornerX  " + mCornerX + "  mCornerX  " + mCornerX);
		 Log.i("hmg", "mBezierControl1.x  " + mBezierControl1.x + "  mBezierControl1.y  " + mBezierControl1.y + "  mBezierControl2.y  " + mBezierControl2.y);*/
		if(Float.NEGATIVE_INFINITY == mBezierControl2.y){
			mBezierControl2.y = minSS;
		}else{
			minSS = mBezierControl2.y;
		}
		mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x)
				/ 2;
		mBezierStart1.y = mCornerY;
		
		// 当mBezierStart1.x < 0或者mBezierStart1.x > 480时
		// 如果继续翻页，会出现BUG故在此限制
		if (mTouch.x > 0 && mTouch.x < mWidth) {
			if (mBezierStart1.x < 0 || mBezierStart1.x > mWidth) {
				if (mBezierStart1.x < 0)
					mBezierStart1.x = mWidth - mBezierStart1.x;

				float f1 = Math.abs(mCornerX - mTouch.x);
				float f2 = mWidth * f1 / mBezierStart1.x;
				mTouch.x = Math.abs(mCornerX - f2);

				float f3 = Math.abs(mCornerX - mTouch.x)
						* Math.abs(mCornerY - mTouch.y) / f1;
				mTouch.y = Math.abs(mCornerY - f3);

				mMiddleX = (mTouch.x + mCornerX) / 2;
				mMiddleY = (mTouch.y + mCornerY) / 2;

				mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
						* (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
				mBezierControl1.y = mCornerY;

				mBezierControl2.x = mCornerX;
				mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
						* (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
				// Log.i("hmg", "mTouchX --> " + mTouch.x + "  mTouchY-->  "
				// + mTouch.y);
				// Log.i("hmg", "mBezierControl1.x--  " + mBezierControl1.x
				// + "  mBezierControl1.y -- " + mBezierControl1.y);
				// Log.i("hmg", "mBezierControl2.x -- " + mBezierControl2.x
				// + "  mBezierControl2.y -- " + mBezierControl2.y);
				mBezierStart1.x = mBezierControl1.x
						- (mCornerX - mBezierControl1.x) / 2;
			}
		}
		mBezierStart2.x = mCornerX;
		mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y)
				/ 2;

		mTouchToCornerDis = (float) Math.hypot((mTouch.x - mCornerX),
				(mTouch.y - mCornerY));

		mBezierEnd1 = getCross(mTouch, mBezierControl1, mBezierStart1,
				mBezierStart2);
		mBezierEnd2 = getCross(mTouch, mBezierControl2, mBezierStart1,
				mBezierStart2);

		// Log.i("hmg", "mBezierEnd1.x  " + mBezierEnd1.x + "  mBezierEnd1.y  "
		// + mBezierEnd1.y);
		// Log.i("hmg", "mBezierEnd2.x  " + mBezierEnd2.x + "  mBezierEnd2.y  "
		// + mBezierEnd2.y);

		/*
		 * mBeziervertex1.x 推导
		 * ((mBezierStart1.x+mBezierEnd1.x)/2+mBezierControl1.x)/2 化简等价于
		 * (mBezierStart1.x+ 2*mBezierControl1.x+mBezierEnd1.x) / 4
		 */
		mBeziervertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4;
		mBeziervertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4;
		mBeziervertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4;
		mBeziervertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4;
	}

	private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {
		mPath0.reset();
		mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);
		mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,
				mBezierEnd1.y);
		mPath0.lineTo(mTouch.x, mTouch.y);
		mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);
		mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,
				mBezierStart2.y);
		mPath0.lineTo(mCornerX, mCornerY);
		mPath0.close();

		canvas.save();
		canvas.clipPath(path, Region.Op.XOR);
		canvas.drawBitmap(bitmap, 0, 0, null);
		canvas.restore();
	}

	private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {
		mPath1.reset();
		mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);
		mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
		mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);
		mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
		mPath1.lineTo(mCornerX, mCornerY);
		mPath1.close();

		mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x
				- mCornerX, mBezierControl2.y - mCornerY));
		int leftx;
		int rightx;
		GradientDrawable mBackShadowDrawable;
		if (mIsRTandLB) {
			leftx = (int) (mBezierStart1.x);
			rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4);
			mBackShadowDrawable = mBackShadowDrawableLR;
		} else {
			leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4);
			rightx = (int) mBezierStart1.x;
			mBackShadowDrawable = mBackShadowDrawableRL;
		}
		canvas.save();
		canvas.clipPath(mPath0);
		canvas.clipPath(mPath1, Region.Op.INTERSECT);
		canvas.drawBitmap(bitmap, 0, 0, null);
		canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
		mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,
				(int) (mMaxLength + mBezierStart1.y));
		mBackShadowDrawable.draw(canvas);
		canvas.restore();
	}


	@Override
	protected void onDraw(Canvas canvas) {
		if(FLIP_WAY == FW_SIMULAT){
			canvas.drawColor(0xFFAAAAAA);
			calcPoints();
			//Log.d("", msg);
			drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);
			drawNextPageAreaAndShadow(canvas, mNextPageBitmap);
			drawCurrentPageShadow(canvas);
			drawCurrentBackArea(canvas, mCurPageBitmap);
		}else{
			drawCurrentPageArea0(canvas, mCurPageBitmap);
			drawNextPageArea0(canvas, mNextPageBitmap);
		}
		
	}
	
	

	/**
	 * Author : hmg25 Version: 1.0 Description : 创建阴影的GradientDrawable
	 */
	private void createDrawable() {
		int[] color = { 0x333333, 0xb0333333 };
		mFolderShadowDrawableRL = new GradientDrawable(
				GradientDrawable.Orientation.RIGHT_LEFT, color);
		mFolderShadowDrawableRL
				.setGradientType(GradientDrawable.LINEAR_GRADIENT);

		mFolderShadowDrawableLR = new GradientDrawable(
				GradientDrawable.Orientation.LEFT_RIGHT, color);
		mFolderShadowDrawableLR
				.setGradientType(GradientDrawable.LINEAR_GRADIENT);

		mBackShadowColors = new int[] { 0xff111111, 0x111111 };
		mBackShadowDrawableRL = new GradientDrawable(
				GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);
		mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);
		
		mBackShadowColors0 = new int[] { 0xff666666, 0x666666 };
		mBackShadowDrawableRL0 = new GradientDrawable(
				GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors0);
		mBackShadowDrawableRL0.setGradientType(GradientDrawable.LINEAR_GRADIENT);
		
		mBackShadowDrawableRL1 = new GradientDrawable(
				GradientDrawable.Orientation.BOTTOM_TOP, mBackShadowColors0);
		mBackShadowDrawableRL1.setGradientType(GradientDrawable.LINEAR_GRADIENT);
		

		mBackShadowDrawableLR = new GradientDrawable(
				GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);
		mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);

		mFrontShadowColors = new int[] { 0x80111111, 0x111111 };
		mFrontShadowDrawableVLR = new GradientDrawable(
				GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);
		mFrontShadowDrawableVLR
				.setGradientType(GradientDrawable.LINEAR_GRADIENT);
		mFrontShadowDrawableVRL = new GradientDrawable(
				GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);
		mFrontShadowDrawableVRL
				.setGradientType(GradientDrawable.LINEAR_GRADIENT);

		mFrontShadowDrawableHTB = new GradientDrawable(
				GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);
		mFrontShadowDrawableHTB
				.setGradientType(GradientDrawable.LINEAR_GRADIENT);

		mFrontShadowDrawableHBT = new GradientDrawable(
				GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);
		mFrontShadowDrawableHBT
				.setGradientType(GradientDrawable.LINEAR_GRADIENT);
	}

	/**
	 * Author : hmg25 Version: 1.0 Description : 绘制翻起页的阴影
	 */
	public void drawCurrentPageShadow(Canvas canvas) {
		double degree;
		if (mIsRTandLB) {
			degree = Math.PI
					/ 4
					- Math.atan2(mBezierControl1.y - mTouch.y, mTouch.x
							- mBezierControl1.x);
		} else {
			degree = Math.PI
					/ 4
					- Math.atan2(mTouch.y - mBezierControl1.y, mTouch.x
							- mBezierControl1.x);
		}
		// 翻起页阴影顶点与touch点的距离
		double d1 = (float) 25 * 1.414 * Math.cos(degree);
		double d2 = (float) 25 * 1.414 * Math.sin(degree);
		float x = (float) (mTouch.x + d1);
		float y;
		if (mIsRTandLB) {
			y = (float) (mTouch.y + d2);
		} else {
			y = (float) (mTouch.y - d2);
		}
		mPath1.reset();
		mPath1.moveTo(x, y);
		mPath1.lineTo(mTouch.x, mTouch.y);
		mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);
		mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);
		mPath1.close();
		float rotateDegrees;
		canvas.save();

		canvas.clipPath(mPath0, Region.Op.XOR);
		canvas.clipPath(mPath1, Region.Op.INTERSECT);
		int leftx;
		int rightx;
		GradientDrawable mCurrentPageShadow;
		if (mIsRTandLB) {
			leftx = (int) (mBezierControl1.x);
			rightx = (int) mBezierControl1.x + 25;
			mCurrentPageShadow = mFrontShadowDrawableVLR;
		} else {
			leftx = (int) (mBezierControl1.x - 25);
			rightx = (int) mBezierControl1.x + 1;
			mCurrentPageShadow = mFrontShadowDrawableVRL;
		}

		rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouch.x
				- mBezierControl1.x, mBezierControl1.y - mTouch.y));
		canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);
		mCurrentPageShadow.setBounds(leftx,
				(int) (mBezierControl1.y - mMaxLength), rightx,
				(int) (mBezierControl1.y));
		mCurrentPageShadow.draw(canvas);
		canvas.restore();

		mPath1.reset();
		mPath1.moveTo(x, y);
		mPath1.lineTo(mTouch.x, mTouch.y);
		mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);
		mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
		mPath1.close();
		canvas.save();
		canvas.clipPath(mPath0, Region.Op.XOR);
		canvas.clipPath(mPath1, Region.Op.INTERSECT);
		if (mIsRTandLB) {
			leftx = (int) (mBezierControl2.y);
			rightx = (int) (mBezierControl2.y + 25);
			mCurrentPageShadow = mFrontShadowDrawableHTB;
		} else {
			leftx = (int) (mBezierControl2.y - 25);
			rightx = (int) (mBezierControl2.y + 1);
			mCurrentPageShadow = mFrontShadowDrawableHBT;
		}
		rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y
				- mTouch.y, mBezierControl2.x - mTouch.x));
		canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);
		float temp;
		if (mBezierControl2.y < 0)
			temp = mBezierControl2.y - mHeight;
		else
			temp = mBezierControl2.y;

		int hmg = (int) Math.hypot(mBezierControl2.x, temp);
		if (hmg > mMaxLength)
			mCurrentPageShadow
					.setBounds((int) (mBezierControl2.x - 25) - hmg, leftx,
							(int) (mBezierControl2.x + mMaxLength) - hmg,
							rightx);
		else
			mCurrentPageShadow.setBounds(
					(int) (mBezierControl2.x - mMaxLength), leftx,
					(int) (mBezierControl2.x), rightx);

		
		mCurrentPageShadow.draw(canvas);
		canvas.restore();
	}

	/**
	 * Author : hmg25 Version: 1.0 Description : 绘制翻起页背面
	 */
	private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {
		int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2;
		float f1 = Math.abs(i - mBezierControl1.x);
		int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2;
		float f2 = Math.abs(i1 - mBezierControl2.y);
		float f3 = Math.min(f1, f2);
		mPath1.reset();
		mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);
		mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
		mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);
		mPath1.lineTo(mTouch.x, mTouch.y);
		mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);
		mPath1.close();
		GradientDrawable mFolderShadowDrawable;
		int left;
		int right;
		if (mIsRTandLB) {
			left = (int) (mBezierStart1.x - 1);
			right = (int) (mBezierStart1.x + f3 + 1);
			mFolderShadowDrawable = mFolderShadowDrawableLR;
		} else {
			left = (int) (mBezierStart1.x - f3 - 1);
			right = (int) (mBezierStart1.x + 1);
			mFolderShadowDrawable = mFolderShadowDrawableRL;
		}
		canvas.save();
		canvas.clipPath(mPath0);
		canvas.clipPath(mPath1, Region.Op.INTERSECT);

		mPaint.setColorFilter(mColorMatrixFilter);

		float dis = (float) Math.hypot(mCornerX - mBezierControl1.x,
				mBezierControl2.y - mCornerY);
		float f8 = (mCornerX - mBezierControl1.x) / dis;
		float f9 = (mBezierControl2.y - mCornerY) / dis;
		mMatrixArray[0] = 1 - 2 * f9 * f9;
		mMatrixArray[1] = 2 * f8 * f9;
		mMatrixArray[3] = mMatrixArray[1];
		mMatrixArray[4] = 1 - 2 * f8 * f8;
		mMatrix.reset();
		mMatrix.setValues(mMatrixArray);
		mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y);
		mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);
		canvas.drawBitmap(bitmap, mMatrix, mPaint);
		// canvas.drawBitmap(bitmap, mMatrix, null);
		mPaint.setColorFilter(null);
		canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
		mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,
				(int) (mBezierStart1.y + mMaxLength));
		mFolderShadowDrawable.draw(canvas);
		canvas.restore();
	}

	public void computeScroll() {
		super.computeScroll();
		if (mScroller.computeScrollOffset()) {
			float x = mScroller.getCurrX();
			float y = mScroller.getCurrY();
			mTouch.x = x;
			mTouch.y = y;
			postInvalidate();
		}
	}
	
	private void drawCurrentPageArea0(Canvas canvas, Bitmap bitmap) {

		float mTouchx = 0;
		float mTouchy = 0;
		canvas.save();
		if(FLIP_WAY == FW_SLIDE_RL){
			mTouchx = -(mWidth - mTouch.x);
		}else if(FLIP_WAY == FW_SLIDE_UD){
			mTouchy = -(mHeight - mTouch.y);
		}
		canvas.translate(mTouchx, mTouchy);
		canvas.drawBitmap(bitmap, 0, 0, null);
		canvas.restore();
		
	}

	
	private void drawNextPageArea0(Canvas canvas, Bitmap bitmap) {
		canvas.save();
		GradientDrawable mCurrentPageShadow;
		
		if(FLIP_WAY == FW_DRAG_RL || FLIP_WAY == FW_SLIDE_RL){
			if(FLIP_WAY == FW_DRAG_RL && mTouch.x<=mWidth-5){
				mCurrentPageShadow = mBackShadowDrawableRL0;
				mCurrentPageShadow.setBounds((int)(mTouch.x - 15), 0, (int)(mTouch.x), mHeight);
				mCurrentPageShadow.draw(canvas);
			}
			mTouch.y = 0;
		}else if(FLIP_WAY == FW_DRAG_UD || FLIP_WAY == FW_SLIDE_UD){
			if(FLIP_WAY == FW_DRAG_UD && mTouch.y<=mHeight-5){
				mCurrentPageShadow = mBackShadowDrawableRL1;
				mCurrentPageShadow.setBounds(0, (int)(mTouch.y - 15), mWidth, (int)mTouch.y);
				mCurrentPageShadow.draw(canvas);
			}
			mTouch.x = 0;
		}
		
		canvas.translate(mTouch.x, mTouch.y);
		canvas.drawBitmap(bitmap, 0, 0, null);
		canvas.restore();
	}

	private void startAnimation(int delayMillis) {
		int dx = 0, dy = 0;
		// dx 水平方向滑动的距离，负值会使滚动向左滚动
		// dy 垂直方向滑动的距离，负值会使滚动向上滚动
		if(FW_SIMULAT == FLIP_WAY){
			if (mCornerX > 0) {
				dx = -(int) (mWidth + mTouch.x);
			} else {
				dx = (int) (mWidth - mTouch.x + mWidth);
			}
			if (mCornerY > 0) {
				dy = (int) (mHeight - mTouch.y);
			} else {
				dy = (int) (1 - mTouch.y); // 防止mTouch.y最终变为0
			}
		}else{
			if (mCornerX > 0) {
				dx = -(int) (mTouch.x);
			} else {
				dx = (int) (mWidth - mTouch.x);
			}
			if (mCornerY > 0) {
				dy = -(int) (mTouch.y);
			} else {
				dy = (int) (mHeight - mTouch.y); // 防止mTouch.y最终变为0
			}
		}
		
		mScroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy,
				delayMillis);
	}

	public void abortAnimation() {
		if (!mScroller.isFinished()) {
			mScroller.abortAnimation();
		}
	}

	public boolean canDragOver() {
		if (mTouchToCornerDis > mWidth / 10)
			return true;
		return false;
	}

	/**
	 * Author : hmg25 Version: 1.0 Description : 是否从左边翻向右边
	 */
	public boolean DragToRight() {
		if(FLIP_WAY == FW_DRAG_RL || FLIP_WAY == FW_SLIDE_RL){
			if (mCornerX > 0)
				return false;
		}else if(FLIP_WAY == FW_DRAG_UD || FLIP_WAY == FW_SLIDE_UD){
			if (mCornerY > 0)
				return false;
		}else{
			if (mCornerX > 0)
				return false;
		}
		
		return true;
	}

	public void onDraw0(Canvas c) {
		FontMetrics fm = mPaint.getFontMetrics();
		float y0 = (float) (Math.ceil(fm.descent - fm.ascent)+mSize/2);
		Vector<String> m_lines = BookPageFactory.getInstance().getLines();
		if (m_lines.size() > 0) {
			
			 if (readbg == null) 
				 c.drawColor(0xff000000); 
			 else
			 c.drawBitmap(readbg, 0, 0, null);
			 
			int y = 30;
			for (String strLine : m_lines) {
				y += y0;
				c.drawText(strLine, 20, y, mPaint);
			}
			Paint p1 = new Paint();
			p1.setColor(mPaint.getColor());
			p1.setAntiAlias(true);
			p1.setTextSize(14*mDensity);
			FontMetrics fm0 = p1.getFontMetrics();
			c.drawText("文字名字", 20, 5+(float)Math.ceil(fm0.descent - fm0.ascent), p1);
			
			Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.dot_line);
			c.drawBitmap(b, 0, 40, p1);
			
			String tt = "4/6";
			Paint p2 = new Paint();
			p2.setColor(mPaint.getColor());
			p2.setAntiAlias(true);
			p2.setTextSize(14*mDensity);
			c.drawText(tt, (mWidth - p2.measureText(tt))/2, mHeight-15, p2);
		}
	}

	public void onFirst() {
		//BookPageFactory.getInstance().nextPage();
		onDraw0(mCurPageCanvas);
		onDraw0(mNextPageCanvas);
	}

	private OnCmdListener mOnClickListener;

	public void setOnSingleTapUpListener(OnCmdListener onClickListener) {
		mOnClickListener = onClickListener;
	}
	
	/**
	 * 设置字体
	 */
	public void setTypeface(){
		String family = ReaderSet.getInstance().getFontFamily();
		int fontStyle = ReaderSet.getInstance().getFontStyle();
		if(family.equals("MONOSPACE")){
			if(fontStyle == Typeface.NORMAL){
				 mPaint.setFakeBoldText(false);
				 mPaint.setTextSkewX(0f);
			}else if(fontStyle == Typeface.BOLD){
				 mPaint.setFakeBoldText(true);
			}else if(fontStyle == Typeface.ITALIC){
				mPaint.setTextSkewX(-0.25f);
			}else if(fontStyle == Typeface.BOLD_ITALIC){
				 mPaint.setFakeBoldText(true);
				 mPaint.setTextSkewX(-0.25f);
			}else if(fontStyle == Paint.UNDERLINE_TEXT_FLAG){
				mPaint.setUnderlineText(true);
			}
		}
		mPaint.setTypeface(Typeface.create(family, fontStyle));
		BookPageFactory.getInstance().setFontFamilly(family,fontStyle);
	}
	
	/**
	 * 设置主题
	 * @param resId
	 * @param color
	 */
	public void setReaderBg(int resId,int color){
		if(readbg != null && !readbg.isRecycled()){
			readbg.recycle();
		}
		Bitmap readbg0 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.wallpaper1);
		readbg = Bitmap.createScaledBitmap(readbg0, mWidth, mHeight, false);
		if(!readbg0.isRecycled()){
			readbg0.recycle();
		}
		
		fontColor = color;
		mPaint.setColor(fontColor);
		
	}
	
	public void setReaderTextSize(float size, float density) {
		BookPageFactory.getInstance().setFontSize(size * density);
		mPaint.setTextSize(size*density);
		this.invalidate();
	}
	
	private float mSize;
	public void setLineSpace(float size){
		BookPageFactory.getInstance().setLineSpace(size);
		mSize =size;
	}
	
	public void reFreshPage(){
		BookPageFactory.getInstance().refreshPage();
		onDraw0(mCurPageCanvas);
		onDraw0(mNextPageCanvas);
		
		this.postInvalidate();
	}
	
	public boolean nextPage(){
		
		//String text = BookPageFactory1.getInstance().nextPage();
		
		if(BookPageFactory.getInstance().isLastPage()){
			mOnClickListener.onCmdHandle(OnCmdListener.CMD_1);
			//Toast.makeText(mContext, "已经是最后一页了", Toast.LENGTH_SHORT).show();
			return false;
		}else{
			BookPageFactory.getInstance().nextPage();
			return true;
		}
	}

	public void destory(){
		if(mCurPageBitmap!=null && !mCurPageBitmap.isRecycled()){
			mCurPageBitmap.recycle();
		}
		if(mNextPageBitmap!=null && !mNextPageBitmap.isRecycled()){
			mNextPageBitmap.recycle();
		}
		if(readbg != null && !readbg.isRecycled()){
			readbg.recycle();
		}
	}
	
}
